import numpy as np
import opuslib
import logging
import time
from typing import Tuple

# 客户端配置类（简化版，仅包含AudioProcessor需要的部分）
class ClientConfig:
    def __init__(self, **kwargs):
        self.audio = {
            'sample_rate': kwargs.get('sample_rate', 16000),
            'channels': kwargs.get('channels', 1),
            'frame_duration': kwargs.get('frame_duration', 10),
            'device_id': kwargs.get('device_id'),
        }
        
        self.silence = {
            'threshold': kwargs.get('silence_threshold', 0.0001),
            'duration': kwargs.get('silence_duration', 1.5),
        }

# 音频处理器实现
class AudioProcessor:
    def __init__(self, config: ClientConfig):
        self.logger = logging.getLogger("xiaozhi")
        self.config = config
        self.sample_rate = config.audio['sample_rate']
        self.channels = config.audio['channels']
        self.frame_duration = config.audio['frame_duration']
        self.frame_size = int(self.sample_rate * self.frame_duration / 1000)

        # 初始化Opus编码器
        self.encoder = opuslib.Encoder(
            self.sample_rate,
            self.channels,
            opuslib.APPLICATION_VOIP
        )

        # 音量检测参数
        self.silence_threshold = config.silence['threshold']
        self.last_voice_time = 0
        
        # 添加缓冲区用于flush操作
        self.buffer = []

    # 添加更新帧设置的方法
    def update_frame_settings(self, frame_duration_ms=None, sample_rate=None):
        """更新音频帧设置
        
        Args:
            frame_duration_ms: 新的帧持续时间(毫秒)
            sample_rate: 新的采样率
        """
        if frame_duration_ms is not None:
            self.frame_duration = frame_duration_ms
            self.logger.info(f"更新帧持续时间为: {frame_duration_ms}ms")
            
        if sample_rate is not None and sample_rate != self.sample_rate:
            self.sample_rate = sample_rate
            self.logger.info(f"更新采样率为: {sample_rate}Hz")
            
            # 如果采样率变化了，需要重新初始化Opus编码器
            self.encoder = opuslib.Encoder(
                self.sample_rate,
                self.channels,
                opuslib.APPLICATION_VOIP
            )
            
        # 更新帧大小
        self.frame_size = int(self.sample_rate * self.frame_duration / 1000)
        self.logger.info(f"帧大小更新为: {self.frame_size}样本")
    
    def flush_buffer(self):
        """刷新缓冲区中的剩余数据"""
        result = self.buffer.copy()
        self.buffer.clear()
        return result

    def process_audio(self, indata: np.ndarray, device_sample_rate: int) -> Tuple[bytes, float]:
        """处理音频数据

        Args:
            indata: 输入的音频数据
            device_sample_rate: 设备采样率

        Returns:
            tuple[bytes, float]: (处理后的音频数据, 音量值)
        """
        try:
            # 计算音量
            volume = np.abs(indata).mean()

            # 如果需要重采样
            if device_sample_rate != self.sample_rate:
                audio_data = self._resample_audio(indata, device_sample_rate)
            else:
                audio_data = indata

            # 编码为Opus格式
            opus_data = self.encoder.encode(audio_data.tobytes(), self.frame_size)

            return opus_data, volume

        except Exception as e:
            self.logger.error(f"音频处理错误: {e}")
            raise

    def _resample_audio(self, indata: np.ndarray, device_sample_rate: int) -> np.ndarray:
        """重采样音频数据"""
        samples_count = int(len(indata) * self.sample_rate / device_sample_rate)
        resampled_data = np.interp(
            np.linspace(0, len(indata), samples_count),
            np.arange(len(indata)),
            indata.reshape(-1)
        ).astype(np.int16)
        return resampled_data

    def is_silence(self, volume: float, current_time: float) -> bool:
        """检查是否静音"""
        if volume >= self.silence_threshold:
            self.last_voice_time = current_time
            return False
        return (current_time - self.last_voice_time) > self.config.silence['duration'] 